﻿/*
** Xin YUAN, 2021, BSD (2)
*/

////////////////////////////////////////////////////////////////////////////////
#ifndef __CTL_DEF_H__
#define __CTL_DEF_H__
////////////////////////////////////////////////////////////////////////////////

#include "_system_/basic_headers.h"
#include "_system_/basic_types.h"

////////////////////////////////////////////////////////////////////////////////
namespace CTL {
////////////////////////////////////////////////////////////////////////////////

//classes

// ExceptionTraits

class ExceptionTraits
{
public:
	static void ThrowInvalid()
	{
		throw ctl_invalid_exception();
	}
	static void ThrowMemory()
	{
		throw ctl_memory_exception();
	}
	static void ThrowOverflow()
	{
		throw ctl_overflow_exception();
	}
	static void ThrowUnexpected()
	{
		throw ctl_unexpected_exception();
	}
};

// NumericTraits<T>

template <typename T>
class NumericTraits
{
public:
	static constexpr const T MinValue = ctl_limits<T>::Lowest;
	static constexpr const T MaxValue = ctl_limits<T>::Max;
};

// ArithmeticTraits<T>

template <typename T>
class ArithmeticTraits
{
public:
	static bool Add(T t1, T t2, T& r) noexcept
	{
		T t = t1 + t2;
		if ( t < t1 )
			return false;
		r = t;
		return true;
	}
	static bool Multiply(T t1, T t2, T& r) noexcept
	{
		//avoid divide 0
		if ( t1 == 0 ) {
			r = 0;
			return true;
		}
		if ( NumericTraits<T>::MaxValue / t1 < t2 )
			return false;
		r = t1 * t2;
		return true;
	}
	static T AddThrow(T t1, T t2)
	{
		T r;
		if ( !Add(t1, t2, r) )
			ExceptionTraits::ThrowOverflow();  //throw
		return r;
	}
	static T MultiplyThrow(T t1, T t2)
	{
		T r;
		if ( !Multiply(t1, t2, r) )
			ExceptionTraits::ThrowOverflow();  //throw
		return r;
	}
};

// NumberTraits<T>

template <typename T>
class NumberTraits
{
public:
	static T Abs(T t) noexcept
	{
		return ctl_abs(t);
	}
	static bool IsOdd(T t) noexcept
	{
		return (t & (T)1) != 0;
	}
};

// FloatTraits<T>

template <typename T>
class FloatTraits
{
public:
	static bool isfinite(T t) noexcept
	{
		int c = ::fpclassify(t);
		return c != FP_NAN && c != FP_INFINITE;
	}
	static T acos(T t) noexcept
	{
		return ctl_acos(t);
	}
	static T acosh(T t) noexcept
	{
		return ctl_acosh(t);
	}
	static T asin(T t) noexcept
	{
		return ctl_asin(t);
	}
	static T asinh(T t) noexcept
	{
		return ctl_asinh(t);
	}
	static T atan2(T t1, T t2) noexcept
	{
		return ctl_atan2(t1, t2);
	}
	static T atanh(T t) noexcept
	{
		return ctl_atanh(t);
	}
	static T cos(T t) noexcept
	{
		return ctl_cos(t);
	}
	static T cosh(T t) noexcept
	{
		return ctl_cosh(t);
	}
	static T exp(T t) noexcept
	{
		return ctl_exp(t);
	}
	static T ldexp(T t, int e) noexcept
	{
		return ctl_ldexp(t, e);
	}
	static T log(T t) noexcept
	{
		return ctl_log(t);
	}
	static T log10(T t) noexcept
	{
		return ctl_log10(t);
	}
	static T log2(T t) noexcept
	{
		return ctl_log2(t);
	}
	static T pow(T t1, T t2) noexcept
	{
		return ctl_pow(t1, t2);
	}
	static T sin(T t) noexcept
	{
		return ctl_sin(t);
	}
	static T sinh(T t) noexcept
	{
		return ctl_sinh(t);
	}
	static T sqrt(T t) noexcept
	{
		return ctl_sqrt(t);
	}
	static T tan(T t) noexcept
	{
		return ctl_tan(t);
	}
	static T tanh(T t) noexcept
	{
		return ctl_tanh(t);
	}
	static T ceil(T t) noexcept
	{
		return ctl_ceil(t);
	}
	static T floor(T t) noexcept
	{
		return ctl_floor(t);
	}
	static T round(T t) noexcept
	{
		return ctl_round(t);
	}
	static T trunc(T t) noexcept
	{
		return ctl_trunc(t);
	}
};

// ByteOrderTraits

class ByteOrderTraits
{
public:
	static bool IsBigEndianHost() noexcept
	{
		uint32_t u = 1;
		return *((uint8_t*)(&u)) != 0x01;
	}
	template <typename T>
	static T Swap(T x) noexcept
	{
		return ctl_byte_order_swap(x);
	}
};

// MemoryTraits

class MemoryTraits
{
public:
	static void Copy(const void* src, uintptr_t size, void* dest) noexcept
	{
		::memcpy(dest, src, size);
	}
	static void Move(const void* src, uintptr_t size, void* dest) noexcept
	{
		::memmove(dest, src, size);
	}
	static void Zero(void* dest, uintptr_t size) noexcept
	{
		::memset(dest, 0, size);
	}
	static void Fill(uint8_t value, void* dest, uintptr_t size) noexcept
	{
		::memset(dest, value, size);
	}
};

// AllocatorTraits

class AllocatorTraits
{
public:
	static void* Allocate(uintptr_t size) noexcept
	{
		return ::malloc(size);
	}
	static void* Reallocate(void* p, uintptr_t size) noexcept
	{
		return ::realloc(p, size);
	}
	static void Free(void* p) noexcept
	{
		::free(p);
	}
};

// CharTraits<Tchar>

template <typename Tchar>
class CharTraits
{
public:
	typedef Tchar  CharType;

	static CharType ToLower(CharType ch) noexcept
	{
		return ctl_to_lower(ch);
	}
	static CharType ToUpper(CharType ch) noexcept
	{
		return ctl_to_upper(ch);
	}
	static bool IsAlnum(CharType ch) noexcept
	{
		return ctl_is_alnum(ch);
	}
	static bool IsAlpha(CharType ch) noexcept
	{
		return ctl_is_alpha(ch);
	}
	static bool IsCntrl(CharType ch) noexcept
	{
		return ctl_is_cntrl(ch);
	}
	static bool IsGraph(CharType ch) noexcept
	{
		return ctl_is_graph(ch);
	}
	static bool IsLower(CharType ch) noexcept
	{
		return ctl_is_lower(ch);
	}
	static bool IsUpper(CharType ch) noexcept
	{
		return ctl_is_upper(ch);
	}
	static bool IsDigit(CharType ch) noexcept
	{
		return ctl_is_digit(ch);
	}
	static bool IsXdigit(CharType ch) noexcept
	{
		return ctl_is_xdigit(ch);
	}
	static bool IsBlank(CharType ch) noexcept
	{
		return ctl_is_blank(ch);
	}
	static bool IsSpace(CharType ch) noexcept
	{
		return ctl_is_space(ch);
	}
	static bool IsPrint(CharType ch) noexcept
	{
		return ctl_is_print(ch);
	}
	static bool IsPunct(CharType ch) noexcept
	{
		return ctl_is_punct(ch);
	}
	static uintptr_t CalcLength(const CharType* sz) noexcept
	{
		return ctl_calc_length(sz);
	}
};

/*
compare trait : T
	static bool IsEQ(const T& t1, const T& t2) noexcept;
	static bool IsNE(const T& t1, const T& t2) noexcept;
	static bool IsGT(const T& t1, const T& t2) noexcept;
	static bool IsLT(const T& t1, const T& t2) noexcept;
	static bool IsGE(const T& t1, const T& t2) noexcept;
	static bool IsLE(const T& t1, const T& t2) noexcept;
	static int Compare(const T& t1, const T& t2) noexcept;
*/

// DefaultCompareTrait<T>

template <typename T>
using DefaultCompareTrait = ctl_default_compare_trait<T>;

////////////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////
#endif
////////////////////////////////////////////////////////////////////////////////
